﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using TugasAkhir.Helpers;
using TugasAkhir.Objects;

namespace TugasAkhir.Models
{
    public static class PenggunaModel
    {
        private static Random randomize = new Random();

        private static string RandomString(int length)
        {
            string result = string.Empty;
            string chars = "rezkicantikabcdefghijklmanopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

            for (int i = 0; i < length; i++)
            {
                result += chars[randomize.Next(0, chars.Length - 1)];
            }

            return result;
        }

        private static string Encrypt<T>(string value, string password, string salt)
            where T : SymmetricAlgorithm, new()
        {
            DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));

            SymmetricAlgorithm algorithm = new T();

            byte[] rgbkey = rgb.GetBytes(algorithm.KeySize >> 3);
            byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);

            ICryptoTransform transform = algorithm.CreateEncryptor(rgbkey, rgbIV);

            using (MemoryStream buffer = new MemoryStream())
            {
                using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write))
                {
                    using (StreamWriter writer = new StreamWriter(stream, Encoding.Unicode))
                    {
                        writer.Write(value);
                    }
                }

                return Convert.ToBase64String(buffer.ToArray());
            }
        }

        private static string Decrypt<T>(string text, string password, string salt)
            where T : SymmetricAlgorithm, new()
        {
            DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));

            SymmetricAlgorithm algorithm = new T();

            byte[] rgbkey = rgb.GetBytes(algorithm.KeySize >> 3);
            byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);

            ICryptoTransform transform = algorithm.CreateDecryptor(rgbkey, rgbIV);

            using (MemoryStream buffer = new MemoryStream(Convert.FromBase64String(text)))
            {
                using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Read))
                {
                    using (StreamReader reader = new StreamReader(stream, Encoding.Unicode))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
        }

        public static bool BuatBaru(string username, string idRole)
        {
            string salt = RandomString(20);
            string p = "reintasa";
            string realPassword = Encrypt<AesManaged>(username, p, salt);

            string query = String.Format("INSERT INTO [dbo].[pengguna] VALUES ('{0}' ,'{1}' ,'{2}' ,'{3}')", username, realPassword, salt, idRole);
            return SqlServer.ExecuteNonQuery(query);
        }

        public static bool GetSalt(string username, out string salt)
        {
            var hasilQuery = new DataSet();
            string query = String.Format("SELECT [psalt] FROM [dbo].[pengguna] WHERE [username] = '{0}'", username);

            bool flag = SqlServer.ExecuteReader(query, out hasilQuery);
            if (flag)
            {
                if (hasilQuery.Tables[0] != null && hasilQuery.Tables[0].Rows.Count == 1)
                {
                    salt = hasilQuery.Tables[0].Rows[0][0].ToString();
                    return true;
                }
                else
                {
                    salt = string.Empty;
                    return false;
                }
            }
            else
            {
                salt = string.Empty;
                return false;
            }
        }

        public static bool CekPasswordLama(string username, string passwordLama)
        {
            string salt = string.Empty;
            if (GetSalt(username, out salt))
            {
                string encrypt = Encrypt<AesManaged>(passwordLama, "reintasa", salt);
                string query = "SELECT 1 FROM [pengguna] WHERE [username] = '" + username + "' AND [password] = '" + encrypt + "'";

                var hasilQuery = new DataSet();
                if (SqlServer.ExecuteReader(query, out hasilQuery))
                {
                    if (hasilQuery.Tables[0] != null && hasilQuery.Tables[0].Rows.Count > 0)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        public static bool GantiPassword(string username, string passwordBaru)
        {
            string salt = RandomString(20);
            string p = "reintasa";
            string encrypt = Encrypt<AesManaged>(passwordBaru, p, salt);

            string query = "UPDATE [pengguna] SET [password] = '" + encrypt + "', [psalt] = '" + salt + "' WHERE [username] = '" + username +"'";
            return SqlServer.ExecuteNonQuery(query);
        }

        public static bool Masuk(string username, string password, out string user, out string idRole)
        {
            var hasilQuery = new DataSet();
            string salt = string.Empty;
            string p = "reintasa";

            bool flag = GetSalt(username, out salt);

            if (flag)
            {
                string realPassword = Encrypt<AesManaged>(password, p, salt);
                string query = String.Format("SELECT [id_role], [username] FROM [dbo].[pengguna] WHERE [username] = '{0}' AND [password] = '{1}' AND [psalt] = '{2}'", username, realPassword, salt);

                flag = SqlServer.ExecuteReader(query, out hasilQuery);

                if (flag)
                {
                    if (hasilQuery.Tables[0] != null && hasilQuery.Tables[0].Rows.Count > 0)
                    {
                        idRole = hasilQuery.Tables[0].Rows[0][0].ToString();
                        user = hasilQuery.Tables[0].Rows[0][1].ToString();
                        return true;
                    }
                    else
                    {
                        idRole = string.Empty;
                        user = string.Empty;
                        return false;
                    }
                }
                else
                {
                    idRole = string.Empty;
                    user = string.Empty;
                    return false;
                }
            }
            else
            {
                idRole = string.Empty;
                user = string.Empty;
                return false;
            }

            
        }

        public static bool GetIdLab(DosenObject dosen, out DataSet hasilQuery)
        {
            string query = String.Format("SELECT 'B0' + CONVERT(VARCHAR(5),(CONVERT(int, SUBSTRING([id_role], 3, 2)) - 3)) as [id_laboratorium] FROM [dbo].[pengguna] WHERE [username] = '{0}'", dosen.Nip);
            return SqlServer.ExecuteReader(query, out hasilQuery);
        }
    }
}